
/**
\file
Defines the rainbow::blend_state class.
\author Sean Tromans
*/

#ifndef	RAINBOW_GRAPHICS_DEVICE_BLEND_STATE_HPP
#define	RAINBOW_GRAPHICS_DEVICE_BLEND_STATE_HPP

#include <sun/gl.hpp>
#include <sun/lua/lua_fwd.hpp>
#include <cstdint>

namespace rainbow
{

	namespace channel_mask
	{
		enum enum_
		{
			red = 0x01,
			green = 0x02,
			blue = 0x04,
			alpha = 0x08,
		};

		/** Sets a specific channel in a colour mask. */
		void set_channel( std::uint8_t & mask, bool active, enum_ channel );

		/** Creates a colour mask from 4 flags indicating which channels should be active. */
		std::uint8_t colour_mask( bool r, bool g, bool b, bool a );

		/** Tests if a channel in a specific colour mask is set. */
		bool is_channel_active( std::uint8_t mask, enum_ channel );
	}

	/**
	Defines the settings for a user defined GPU blending mode.
	\author Sean Tromans
	*/
	struct blend_state
	{
		/**
		Default Constructor.
		\author Sean Tromans
		*/
		blend_state( );

		/**
		Applies any changes from the provided blend_state to OpenGL.
		@param other The currently active blend_state.
		\author Sean Tromans
		*/
		void apply( blend_state const & other ) const;

		bool	enabled;	///< Whether or not transparency is active with this state.
		bool	alpha_to_coverage_enabled;	///< Whether to use alpha to coverage.

		GLenum	src_colour;	///< Specifies how the source RGB values are computed.
		GLenum	dst_colour;	///< Specifies how the destination RGB values are computed.

		GLenum	src_alpha;	///< Specifies how the source alpha value is computed.
		GLenum	dst_alpha;	///< Specifies how the destination alpha value is computed.

		GLenum	colour_equation;	///< Specifies the equation to use when blending the source and destination colours.
		GLenum	alpha_equation;		///< Specifies the equation to use when blending the source and destination alpha values.

		std::uint8_t	colour_mask;	///< The colour mask to be applied when rendering using this state.
										///< For portability should be modified using the helper functions in the channel_mask namespace.

		/**
		Exposes the blend_state to lua.
		@param L The Lua State being initialised.
		\author Sean Tromans.
		*/
		static void lua_interface( lua_State * L );
	};

	/**
	Comparrison operator for blend_states.
	@param lhs The first blend_state being compared.
	@param rhs The second blend_state being compared.
	@return True if the blend_states are equal.
	\author Sean Tromans
	*/
	bool operator == ( blend_state const & lhs, blend_state const & rhs );

}

#endif	//RAINBOW_GRAPHICS_DEVICE_BLEND_STATE_HPP
